package com.mimosa.common.web;

import java.io.IOException;
import java.util.Collection;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.mimosa.common.system.menu.MenuItemService;
import com.mimosa.common.system.menu.TMenuItem;
import com.mimosa.common.system.permission.PermissionService;
import com.mimosa.common.system.user.TUser;
import com.mimosa.common.system.user.UserContext;
import com.mimosa.util.config.YesNoType;

/**
 * 检查用户是否已经登陆，如果没有登陆则将用户导向到登陆页面
 * 
 * @filename LoginCheckFilter.java
 * @date 2012-4-21 上午9:23:23
 * @author ggeagle
 * 
 */
public class LoginCheckFilter implements Filter {
	/**
	 * 菜单信息
	 */
	private static final String LOGIN = "logIn";
	/**
	 * 菜单信息
	 */
	private static final String LOG_OUT = "logOut";
	/**
	 * 错误信息显示页面
	 */
	private static final String DENY = "deny";
	/**
	 * 系统初始化的相关信息
	 */
	private static final String SET_UP = "/setup/";
	/**
	 * 菜单信息
	 */
	private MenuItemService menuItemService;
	private PermissionService permissionService;
	static final String CURRENT_PATH_NAME = "currentPath";
	static final String CURRENT_MENU_ID = "currentMenuId";

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1,
			FilterChain arg2) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) arg0;
		String path = request.getServletPath();
		if (StringUtils.containsIgnoreCase(path, LOGIN)
				|| StringUtils.containsIgnoreCase(path, LOG_OUT)
				|| StringUtils.containsIgnoreCase(path, DENY)
				|| StringUtils.containsIgnoreCase(path, SET_UP)) {
			arg2.doFilter(arg0, arg1);
		} else {
			// 获取访问的菜单
			TMenuItem menuItem = this.menuItemService.getVisitMenuItem(path);
			// 获取访问的路径
			HttpSession session = request.getSession();
			// 获取当前登录的用户
			TUser user = (TUser) request.getSession().getAttribute(
					UserContext.USER_ATTR);
			HttpServletResponse response = (HttpServletResponse) arg1;
			// 判断用户是否已登陆，如果已登陆，则将用户定位到登陆页面
			if (menuItem != null) {
				session.setAttribute(CURRENT_PATH_NAME, menuItem.getMenuPath());
				session.setAttribute(CURRENT_MENU_ID, menuItem.getId());
				if (YesNoType.Y.name().equalsIgnoreCase(menuItem.getNeedAuth())) {
					if (user == null || StringUtils.isBlank(user.getId())) {
						session.setAttribute(FilterHelper.RENDER_URL, path);
						// 用户未登陆，将用户定位到登陆页面
						response.sendRedirect(request.getContextPath()
								+ "/logIn.action");
						return;
					} else {
						if (YesNoType.Y.name().equalsIgnoreCase(
								menuItem.getNeedGrant())) {
							String currentUserId = user.getId();
							// 查看用户的访问权限
							Collection<String> collection = this.permissionService
									.getItemsByUid(currentUserId);
							if (!"1".equals(currentUserId)
									&& !collection.contains(menuItem.getId())) {
								// 用户未登陆，将用户定位到登陆页面
								response.sendRedirect(request.getContextPath()
										+ "/deny.action");
								return;
							}
						}
					}
				}
				arg2.doFilter(arg0, arg1);
			} else {
				if (user == null || StringUtils.isBlank(user.getId())) {
					// 用户未登陆，将用户定位到登陆页面
					response.sendRedirect(request.getContextPath()
							+ "/logIn.action");
					return;
				} else {
					arg2.doFilter(arg0, arg1);
				}
			}
		}
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		ApplicationContext applicationContext = WebApplicationContextUtils
				.getRequiredWebApplicationContext(arg0.getServletContext());
		this.menuItemService = (MenuItemService) applicationContext
				.getBean("menuItemService");
		this.permissionService = (PermissionService) applicationContext
				.getBean("permissionService");
	}

	@Override
	public void destroy() {
		this.menuItemService = null;
	}
}